package com.jl.shudu.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.jl.shudu.R;
import com.jl.shudu.interfaces.NumberClickListener;

import java.text.DecimalFormat;

/**
 * 作者： 吴昶 .
 * 时间: 2018/11/26 9:51
 * 功能简介：数独的控件
 */
public class ShuDuView extends View {

    private int[][] number=new int[9][9];//数组保存
    private int[][] original=new int[9][9];//原始数组保存
    private int[][] error=new int[9][9];//错误数组位置保存
    //控件宽高
    private int width;
    private int height;
    //画笔
    private Paint paint;
    //点击屏幕的 原始触点坐标
    private float touchX=0;
    private float touchY=0;
    //点击屏幕的点 在 9 * 9 方格的下标
    private int stateX=-1;
    private int stateY=-1;
    //每个方格的 宽高
    private int step=0;
    //计算下标的格式化工具
    private DecimalFormat decimalFormat=new DecimalFormat("0");
    //数独界面点击事件的监听回调方法
    private NumberClickListener listener;

    //网格 底色 字体颜色等属性值
    private int outlineBorderColor;
    private int inlineBorderColor;
    private int textColor;
    private int promptBackgroundColor;
    private int choseIndexColor;
    private int errorIndexColor;
    //横线 的起始坐标 (h1,ht) 终点坐标（hr,hb）
    float hl=0;
    float ht=0;
    float hr=0;
    float hb=0;
    //竖线 的起始坐标 (h1,ht) 终点坐标（hr,hb）
    float sl=0;
    float st=0;
    float sr=0;
    float sb=0;
    //坐标偏移量
    int deviation=0;

    public ShuDuView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.ShuDuView);
        outlineBorderColor=typedArray.getColor(R.styleable.ShuDuView_outlineBorderColor,getResources().getColor(R.color.shudu_outline_border_color));
        inlineBorderColor=typedArray.getColor(R.styleable.ShuDuView_inlineBorderColor,getResources().getColor(R.color.shudu_inline_border_color));
        textColor=typedArray.getColor(R.styleable.ShuDuView_textColor,getResources().getColor(R.color.shudu_text_color));
        promptBackgroundColor=typedArray.getColor(R.styleable.ShuDuView_promptBackgroundColor,getResources().getColor(R.color.shudu_prompt_background_color));
        choseIndexColor=typedArray.getColor(R.styleable.ShuDuView_choseIndexColor,getResources().getColor(R.color.shudu_chose_index_color));
        errorIndexColor=typedArray.getColor(R.styleable.ShuDuView_errorIndexColor,getResources().getColor(R.color.shudu_error_index_color));
        init();
    }

    private void init(){
        paint=new Paint();
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(1);
        paint.setAntiAlias(true);
    }


    public int[][] getNumber() {
        return number;
    }

    public void setListener(NumberClickListener listener) {
        this.listener = listener;
    }

    /**
     * 传入初始的数组
     * @param number
     */
    public void setNumber(int[][] number) {
        this.number = number;
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                original[i][j]=number[i][j];
            }
        }
        invalidate();
    }

    /**
     * 设置新传入的 数字
     * @param num
     */
    public void setNewNumber(int num){
        if(stateX==-1||stateY==-1 ||original[stateX-1][stateY-1]!=0) return;
        number[stateX-1][stateY-1]=num;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        width=getWidth();
        height=getHeight();
        if(width>height){
            deviation=(width-height)/2;
            width=height;
        }else {
            height=width;
        }
        step=width/9;
        //网格
        for(int x=0;x<10;x++){
            if(x%3==0) {
                paint.setStrokeWidth(4);
                paint.setColor(outlineBorderColor);
                if (x == 9) {
                    hl=0;ht=height;hr=width;hb=height;
                    sl=width;st=0;sr=width;sb=height;
                }else if(x==0){
                    hl=0;ht=2;hr=width;hb=2;
                    sl=0;st=0;sr=0;sb=height;
                }else {
                    hl=0;ht=step*x;hr=width;hb=step*x;
                    sl=step*x;st=0;sr=step*x;sb=height;
                }
            }else {
                paint.setStrokeWidth(1);
                paint.setColor(inlineBorderColor);
                hl=0;ht=step*x;hr=width;hb=step*x;
                sl=step*x;st=0;sr=step*x;sb=height;
            }
            canvas.drawLine(hl+deviation,ht,hr+deviation,hb,paint);
            canvas.drawLine(sl+deviation,st,sr+deviation,sb,paint);
        }
        paint.setStrokeWidth(1);
        //确认点击的区域
        drawNewRect(stateX,stateY,canvas,paint);
        paint.setTextSize(step/2);
        //设置初始化
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                //显示原始提示数字区域 背景色
                if(original[i][j]!=0){
                    paint.setColor(promptBackgroundColor);
                    drawIndex(i,j,canvas,paint);
                }
                // 显示错误数字的背景色
                if(error[i][j]!=0){
                    paint.setColor(errorIndexColor);
                     drawIndex(i,j,canvas,paint);
                }
                //显示已有的数字
                if(number[i][j]!=0){
                    paint.setColor(textColor);
                    canvas.drawText(String.valueOf(number[i][j]),step*(i-0.625f+1)+deviation,step*(j-0.375f+1),paint);
                }
            }
        }
    }

    private void drawIndex(int x,int y,Canvas canvas,Paint paint){
        newRect(step*x+6,step*y+6,step*(x+1)-6,step*(y+1)-6,canvas,paint);
    }

    /**
     * 根据 点击的位置绘制底色
     * @param x
     * @param y
     * @param canvas
     * @param p
     */
    private void drawNewRect(int x,int y,Canvas canvas,Paint p){
        if(x!=-1&&y!=-1){
            //仅在初始化的值为 0 的地方点击有效
            if(x>9||y>9) return;
            if(original[x-1][y-1]!=0){
                if(listener!=null){
                    listener.onOrigialCanNotChange();
                }
                return;
            }
            //边界问题，最后的方格需要进行数值的设置，防止周围出现空白
            int r=0;
            if(stateX==9){
                r=width;
            }else {
                r=step*stateX;
            }
            int b=0;
            if(stateY==9){
                b=height;
            }else {
                b=step*stateY;
            }
            paint.setColor(choseIndexColor);
            newRect(step*(x-1),step*(y-1),r,b,canvas,paint);
            if(listener!=null){
                listener.onClickIndex(x-1,y-1);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                touchX=event.getX();
                touchY=event.getY();
                break;
            case MotionEvent.ACTION_UP:
                float x=Math.abs(touchX-event.getX());
                float y=Math.abs(touchY-event.getY());
                if( x <= 20 && y <= 20 && touchX > deviation){
                    stateX=Integer.valueOf(decimalFormat.format(Math.ceil((touchX-deviation)/step)));
                    stateY=Integer.valueOf(decimalFormat.format(Math.ceil((touchY)/step)));
                    invalidate();
                }
                break;
        }
        return super.onTouchEvent(event);
    }

    private void newRect(int l, int t, int r, int b, Canvas canvas, Paint paint){
        RectF rectF=new RectF(l+deviation,t,r+deviation,b);
        canvas.drawRect(rectF,paint);
    }

    /**
     * 情况所有的数据
     */
    public void clear(){
        number=null;
        original=null;
        error=null;
        number=new int[9][9];
        original=new int[9][9];
        error=new int[9][9];
        invalidate();
    }

    /**
     * 检查结果 是否正确
     */
    public void checkResult(){
        stateY=-1;
        stateX=-1;
        checkIsRight();
    }

    //校验
    private void checkIsRight(){
        boolean right=true;
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                int node=number[i][j];
                if(node==0){
                    listener.onResultIsTrue(false,-1);
                    return;
                }
                //横向检查是否有相同的项 ，检查当前节点往后的节点
                for(int sx=i+1;sx<9;sx++){
                    if(node==number[sx][j]){
                        right=false;
                        error[sx][j]=node;
                        error[i][j]=node;
                    }
                }
                //纵向检查是否有相同的项 ，检查当前节点往下的节点
                for(int sy=j+1;sy<9;sy++){
                    if(node==number[i][sy]){
                        right=false;
                        error[i][sy]=node;
                        error[i][j]=node;
                    }
                }
                //根据下标判断 当前节点所在的 3 X 3 的格子中数字是否重复
                //已重复的数字放入 error 数组对应的下标
                int xi=i/3;
                int yi=j/3;
                for(int vx=0;vx<3;vx++){
                    for(int vy=0;vy<3;vy++){
                        if((3*xi+vx)!=i && (3*yi+vy)!=j){
                            if(node==number[3*xi+vx][3*yi+vy]){
                                right=false;
                                error[3*xi+vx][3*yi+vy]=node;
                                error[i][j]=node;
                            }
                        }
                    }
                }
            }
        }
        listener.onResultIsTrue(right,0);
    }

}
